;;; sudo-save.el --- 

;; Use `write-file-hooks' and `after-save-hook' to run "sudo chown ... " before
;; AND after file save.  This allows the Emacs process to grant ownership to the
;; user and then restore ownership just after save.

;; TODO:
;;
;; - Actually what we SHOULD do is actually do a chown this way and NOT a chmod.
;;
;; - Can sudo cache passwords?  I think it can.
;;
;; - Ability to chmod a+r a file JUST prior to reading it ... and then restoring
;;   permissions RIGHT after it.
;;
;; - Ability to s
;;

;;; History:
  
;;; Code:

(defvar zl-sudo-save-file-uid nil "")
(defvar zl-sudo-save-output-buffer "*sudo output*" "")

(defun zl-sudo-save-after-save-hook()
  "If we've chown'd this file then we should restore it's ownership."

  (when zl-sudo-save-file-uid
    ;;restore original file access.
    (zl-sudo-save-chown (number-to-string zl-sudo-save-file-uid) (buffer-file-name))
    (setq zl-sudo-save-file-uid nil)
    (message "Wrote (with sudo) %s done." (buffer-file-name))))

(defun zl-sudo-save-chown(user file-name)

  (setq buf (get-buffer-create zl-sudo-save-output-buffer))
  (setq proc (start-process "sudo-save-proc" buf "sudo" "chown" user file-name))
  (sleep-for .5)
  (if (and (eq (process-status proc) 'exit)
           (zerop (process-exit-status proc)))
      (message "sudo chown %s %s suceeded." user file-name)
    (progn
      (kill-process proc)
      (message "Error on sudo chown %s %s. status:%s, exit-status:%s" user file-name (process-status proc)(process-exit-status proc))
      (display-buffer buf))))

;;(zl-sudo-save-chown "root" "/home/zhangli/www/id_dsa.pub")

  
(defun zl-sudo-save-write-file-hook()
  "Take ownership of this file and later restore it."

  (make-local-variable 'zl-sudo-save-file-uid)
  (setq zl-sudo-save-file-uid nil)
  ;;call sudo to change the file's modes  
  (when (and (buffer-file-name)
             (not (file-writable-p (buffer-file-name)))
             (yes-or-no-p (format "Read-only file: %s\n\"SUDO SAVE it?\"" (buffer-file-name))))
    ;;store the origin uid of file    
    (setq zl-sudo-save-file-uid (nth 2 (file-attributes (buffer-file-name))))
    (zl-sudo-save-chown "root" (buffer-file-name)))
  ;;return nil to let other hook run
  nil)

(defun zl-sudo-save-find-file-hook()
  "Disable read-only support since this is no obsolete for this file."
  (if (buffer-file-name)
      (if (not (file-writable-p (buffer-file-name)))
          (if (y-or-n-p (format "Read-only file:\"%s\", really make it writable?" (buffer-file-name)))
              (setq buffer-read-only nil)))))
  
;; (when (eq system-type 'gnu/linux)
;;   (add-hook 'write-file-functions 'zl-sudo-save-write-file-hook)
;;   (add-hook 'after-save-hook 'zl-sudo-save-after-save-hook)
;;   (add-hook 'find-file-hook 'zl-sudo-save-find-file-hook))

(provide 'sudo-save)

;;; sudo-save.el ends here
